﻿using CommonTools;
using CommonTools.Class;
using CommonTools.Core;
using CommonTools.FreeProxy;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static int success = 0;
        static string path = Environment.CurrentDirectory + "\\proxy";
        static string filepath = path + "\\result.txt";

        static string uri = config.PollUrl;
        static config config
        {
            get
            {
                return config.GetConfig();
            }
        }
        static void Main(string[] args)
        {
            

            do
            {
                var lasttime = DateTime.Now;
                var proxys = ReadProxy(out lasttime);
                int pageSize = config.ThreadWidth;

                if (lasttime < DateTime.Now.AddMilliseconds(0 - config.ProxyExpire) || proxys.Count == 0)
                {
                    Console.WriteLine("本地代理列表过期，准备抓取代理列表...");
                    try
                    {
                        GetProxyAPI(config.ProxyApi);
                    }
                    catch (FileLoadException ex)
                    {
                        Console.WriteLine(string.Format("抓取代理异常：{0}", ex.Message));
                        Console.WriteLine("尝试从免费代理接口获取代理");
                        GetFreeProxy();
                    }           
                    proxys = ReadProxy(out lasttime);
                    Console.WriteLine("本地代理列表加载完毕...");
                    Console.WriteLine("开始投票...");
                    for (var pageIndex = 0; (pageIndex + 1) * pageSize <= proxys.Count; pageIndex++)
                    {
                        var page = proxys.Skip(pageIndex * pageSize).Take(pageSize).ToList();
                        //Console.WriteLine(string.Format("从{0}到{1}", pageIndex * pageSize + 1, (pageIndex + 1) * pageSize));
                        Vote(uri, page);
                        var status = CheckCurrentStatus();
                        if (!string.IsNullOrWhiteSpace(status))
                            Console.WriteLine(status);
                    }
                }
                else
                {
                    Console.WriteLine(string.Format("距离上次抓取代理列表不足{0}分钟", config.ProxyExpire / (1000 * 60)));
                }
                Console.WriteLine("20秒后重新启动。");
                Thread.Sleep(20000);
            } while (true);


        }
        public static void GetFreeProxy()
        {
            //GetProxyAPI(config.DefaultSetting.ProxyApi);           
            var path = Environment.CurrentDirectory + "\\proxy";
            var filepath = path + "\\result.txt";
            var typeFinder = new TypeFinder();
            var free = typeFinder.FindClassesOfType<IProxy>();
            var q = new List<Proxy>();
            foreach (var f in free)
            {
                var i = (IProxy)Activator.CreateInstance(f);
                q.AddRange(i.GetProxy());                
            }
            File.WriteAllLines(filepath, q.Select(x => string.Format("{0}:{1}", x.IP, x.Port)));
            return;
        }
        public static string CheckCurrentStatus()
        {
            var result = HttpHelper.HttpGet("http://m.fangxinbao.com/wx/voteDetail-160813.html", "", "text/html;charset=gb2312");
            var reg = new Regex("(?<=<span class=\"cff5a1a\">).*?(?=</span>)");
            var m = reg.Matches(result);
            try
            {
                return string.Format("当前排名：{0};共{1}票", m[1].Value, m[2].Value);
            }
            catch (Exception)
            {
                return null;
            }


        }
        public static void Vote(string uri, IList<Proxy> proxys)
        {
            for (var i = 0; i < proxys.Count; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(VoteAction));
                t.Name = "vote-" + i.ToString();
                t.Start(new VotePara
                {
                    i = i,
                    uri = uri,
                    proxy = proxys[i]
                });
                t.Join(500);
                //t.Abort();
                //Console.WriteLine(t.ThreadState.ToString());
            }
            //Console.WriteLine(string.Format("已投{0}票", count));
        }
        public static void TestThread()
        {
            for (var i = 0; i < 50; i++)
            {
                Thread t = new Thread(BaiduTest);
                t.Start();
            }
        }
        public static void BaiduTest()
        {
            try
            {

                var result = HttpHelper.HttpGet("http://www.baidu.com/", "");
                if (string.IsNullOrWhiteSpace(result))
                {
                    Console.WriteLine("Success");
                }
                else
                {
                    Console.WriteLine("Empty");
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Failed");
            }
        }
        public static void VoteAction(object para)
        {

            var p = (VotePara)para;
            var uri = p.uri;
            var proxy = p.proxy;
            //var request = (HttpWebRequest)WebRequest.Create(uri);
            //request.Method = config.PollType;
            //request.ContentType = "application/json";
            //request.Proxy = new WebProxy(proxy.IP, proxy.Port);

            try
            {
                var retString = "";
                switch (config.PollType)
                {
                    case "GET":
                        retString = HttpHelper.HttpGet(uri,"",proxy);break;
                    case "POST":
                        retString = HttpHelper.HttpPost(uri, "", proxy,timeout:config.TimeOut);break;
                    default:
                        Console.WriteLine("提交方式设置错误（GET/POST），退出");
                        return;
                }
                //var response = (HttpWebResponse)request.GetResponse();
                //request.Timeout = config.TimeOut;

                //var myResponseStream = response.GetResponseStream();
                //var myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                //string retString = myStreamReader.ReadToEnd();
                //myStreamReader.Close();
                //myResponseStream.Close();
                
                int resultint = 0;
                if (int.TryParse(retString, out resultint))
                {
                    if (resultint == 2)
                    {
                        success++;
                        Console.WriteLine(string.Format("{2} 线程{1}：投票成功,累计{0}票", success, p.i, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")));
                    }
                    else
                    {
                        Console.WriteLine(string.Format("{1} 线程{0}：投票失败", p.i, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")));
                    }
                }
                else
                {
                    Console.WriteLine(string.Format("{1} 线程{0}：投票失败", p.i, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")));
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("{2} 线程{0}：{1}", p.i, ex.Message, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")));
            }
            return;
        }

        public static void GetProxyAPI(string apiurl=null)
        {
            Console.WriteLine("开始抓取代理列表...");
            var path = Environment.CurrentDirectory + "\\proxy";
            var url = apiurl==null?config.ProxyApi:apiurl;
            var filepath = path + "\\result.txt";
            var result = HttpHelper.HttpGet(url, "");
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            File.WriteAllText(filepath, result);

            var line = File.ReadLines(filepath).FirstOrDefault();
            if (line == null || line.IndexOf("ERROR") > -1)
                throw new FileLoadException(line);


            Console.WriteLine("抓取代理列表成功...");
        }
        public static IList<Proxy> ReadProxy(out DateTime createtime)
        {
            Console.WriteLine("开始读取本地代理列表...");
            var result = new List<Proxy>();
            if (!File.Exists(filepath))
            {
                createtime = DateTime.Now;
                return result;
            }
            var results = File.ReadLines(filepath);
            foreach (var i in results)
            {
                var proxystr = i.Split(':');
                int port = 0;
                if (int.TryParse(proxystr[1], out port))
                {
                    result.Add(new Proxy
                    {
                        IP = proxystr[0],
                        Port = port
                    });
                }
            }
            createtime = File.GetLastWriteTime(filepath);
            return result;
        }
    }
    public class VotePara
    {
        public int i { get; set; }
        public string uri { get; set; }
        public Proxy proxy { get; set; }
    }

}
